package io.github.wppli.domain.user.service;

import cc.jq1024.middleware.redisson.IRedissonClientService;
import cc.jq1024.middleware.redisson.IRedissonService;
import io.github.wppli.domain.user.event.AdjustUserFollowedEvent;
import io.github.wppli.domain.user.model.entity.FollowTaskEntity;
import io.github.wppli.domain.user.model.entity.FollowUserEntity;
import io.github.wppli.domain.user.model.valobj.FollowConstants;
import io.github.wppli.domain.user.repository.IUserRepository;
import io.github.wppli.types.event.BaseEvent;
import io.github.wppli.types.event.TaskStateVO;
import lombok.Builder;
import org.redisson.api.RSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.temporal.TemporalUnit;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author li--jiaqiang 2025−03−02
 */
@Service
public class UserService implements IUserService {

    private static final Logger log = LoggerFactory.getLogger(UserService.class);
    private final IUserRepository userRepository;
    private final IRedissonClientService redissonService;
    private final AdjustUserFollowedEvent adjustUserFollowedEvent;
    private final AdjustAccountService adjustAccountService;
    public UserService(IUserRepository userRepository, IRedissonClientService redissonService, AdjustUserFollowedEvent adjustUserFollowedEvent, AdjustAccountService adjustAccountService) {
        this.userRepository = userRepository;
        this.redissonService = redissonService;
        this.adjustUserFollowedEvent = adjustUserFollowedEvent;
        this.adjustAccountService = adjustAccountService;
    }


    /**
     * userId 取关 unFollowedUserId
     * @param userId 关注者id
     * @param unFollowedUserId 被取消关注者id
     */
    @Override
    public void unfollow(Long userId, Long unFollowedUserId) {
        // 从 redis 中获取 userId 用户的关注列表
        String key = FollowConstants.FOLLOWEE.getPrefix() + userId;
        RSet<Object> userIdFolloweeList = redissonService.getSet(key);
        if (userIdFolloweeList.isEmpty()) {
            // 查询数据库中该用户的关注列表
            List<FollowUserEntity> dbUserIdFolloweeList = adjustAccountService.getFolloweeList(unFollowedUserId);
            if (dbUserIdFolloweeList.isEmpty()) {
                log.info("用户：{} 未关注任何用户", userId);
                return;
            }
            // 删除用户userId关注列表中的用户 unFollowedUserId
            FollowUserEntity targetEntity = userRepository.queryFollowUserInfoById(unFollowedUserId);
            log.info("将用户：{} 从用户：{} 的关注列表中移除", userId, unFollowedUserId);
            dbUserIdFolloweeList.remove(targetEntity);
            // 将数据库信息缓存到 redis
            userIdFolloweeList.addAll(dbUserIdFolloweeList);
            // 设置 10 min 过期时间
            userIdFolloweeList.expire(Duration.ofMinutes(10));
        }

        // 删除用户 unFollowedUserId 的粉丝列表中的用户 userId
        FollowUserEntity userEntity = userRepository.queryFollowUserInfoById(userId);
        log.info("将用户：{} 从用户：{} 的粉丝列表中移除", userId, unFollowedUserId);
        // 删除目标用户的粉丝列表缓存
        String targetKey = FollowConstants.FOLLOWER.getPrefix() + unFollowedUserId;
        RSet<Object> targetUserIdFollowerList = redissonService.getSet(targetKey);
        targetUserIdFollowerList.remove(userEntity);

        // 4. 异步更新数据库 - 用户取消关注 - 使用消息队列
        // 4.1 构建消息实体
        AdjustUserFollowedEvent.AdjustUserFollowedMessage adjustUserFollowedMessage = new AdjustUserFollowedEvent.AdjustUserFollowedMessage(userId, unFollowedUserId, false);

        BaseEvent.EventMessage<AdjustUserFollowedEvent.AdjustUserFollowedMessage> adjustUserFollowedMessageEventMessage = adjustUserFollowedEvent.buildEventMessage(adjustUserFollowedMessage);

        FollowTaskEntity taskEntity = FollowTaskEntity.builder()
                .userId(userId.toString())
                .topic(adjustUserFollowedEvent.topic())
                .state(TaskStateVO.create)
                .messageId(adjustUserFollowedMessageEventMessage.getId())
                .message(adjustUserFollowedMessageEventMessage).build();
        // 4.2 发送消息
        userRepository.unfollow(taskEntity);
    }

    /**
     * userId 关注 followedUserId
     * @param userId 用户ID
     * @param followedUserId 被关注用户ID
     */
    @Override
    public void follow(Long userId, Long followedUserId) {
        // 0. 查询followedUserId用户
        FollowUserEntity followedUserEntity = userRepository.queryFollowUserInfoById(followedUserId);

        // 1. 从redis中获取userId用户的关注列表
        String followeeKey = FollowConstants.FOLLOWEE.getPrefix() + userId;
        RSet<Object> userIdFolloweeList = redissonService.getSet(followeeKey);
        if (userIdFolloweeList.contains(followedUserEntity)) {
            log.info("用户：{} 已经关注用户：{}", userId, followedUserId);
            return;
        }
        if (userIdFolloweeList.isEmpty()) {
            // 从数据库中查询用户关注列表
            List<FollowUserEntity> dbUserIdFolloweeList = adjustAccountService.getFolloweeList(userId);
            dbUserIdFolloweeList.add(followedUserEntity);
            // 2. 将用户 followedUserEntity 添加到该用户的关注列表
            userIdFolloweeList.addAll(dbUserIdFolloweeList);
            userIdFolloweeList.expire(Duration.ofMinutes(10));
        }

        // 查询 followedUserId 用户的粉丝列表
        FollowUserEntity userEntity = userRepository.queryFollowUserInfoById(userId);
        String targetKey = FollowConstants.FOLLOWER.getPrefix() + followedUserId;
        RSet<Object> targetUserIdFollowerList = redissonService.getSet(targetKey);
        // 将用户添加到目标用户的缓存中
        log.info("用户：{} 关注用户：{}", userId, followedUserId);
        targetUserIdFollowerList.add(userEntity);
        targetUserIdFollowerList.expire(Duration.ofMinutes(10));


        // 3. 更新数据库
        // 4.1 构建消息实体
        AdjustUserFollowedEvent.AdjustUserFollowedMessage adjustUserFollowedMessage = new AdjustUserFollowedEvent.AdjustUserFollowedMessage(userId, followedUserId, true);

        BaseEvent.EventMessage<AdjustUserFollowedEvent.AdjustUserFollowedMessage> adjustUserFollowedMessageEventMessage = adjustUserFollowedEvent.buildEventMessage(adjustUserFollowedMessage);

        FollowTaskEntity taskEntity = FollowTaskEntity.builder()
                .userId(userId.toString())
                .topic(adjustUserFollowedEvent.topic())
                .state(TaskStateVO.create)
                .messageId(adjustUserFollowedMessageEventMessage.getId())
                .message(adjustUserFollowedMessageEventMessage).build();
        // 4.2 发送消息
        userRepository.follow(taskEntity);
    }
}